{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c3590899-3033-485c-894a-97bd94acdcb9",
   "metadata": {},
   "source": [
    "# 1. Dataset Preparation for Florence-2 fine tuning for object detection\n",
    "\n",
    "Models: \n",
    "- https://huggingface.co/microsoft/Florence-2-large\n",
    "- https://huggingface.co/microsoft/Florence-2-base\n",
    "\n",
    "Document: https://arxiv.org/abs/2311.06242\n",
    "\n",
    "<img src=\"florence2_1.jpg\">\n",
    "\n",
    "<img src=\"florence2_2.jpg\">"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f35ce62b-fe3b-412c-8a92-e7572944094e",
   "metadata": {},
   "source": [
    "> We are going to use this images dataset: https://universe.roboflow.com/universiti-malaysia-pahang-qcvas/objectdetection-ngxjp/dataset/5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "311e48b2-a7c7-4c57-95d7-6f5c33810d3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import json\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6a96b7a2-aedf-4c8f-b0fc-2d057f93f8b6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'3.10.14 (main, May  6 2024, 19:42:50) [GCC 11.2.0]'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sys.version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6c7ff5b3-f7c6-41d7-82de-4aa0f35347b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def yolo_parsing(annotation_file):\n",
    "    \"\"\"\n",
    "    Parses a YOLO annotation file and converts it into a JSON object with image name, prefix, and suffix.\n",
    "\n",
    "    Args:\n",
    "        annotation_file (str): Path to the YOLO annotation file.\n",
    "\n",
    "    Returns:\n",
    "        dict: A JSON object containing:\n",
    "            - image (str): The name of the image file corresponding to the annotation.\n",
    "            - prefix (str): A constant prefix string \"<OD>\".\n",
    "            - suffix (str): A concatenated string of bounding box descriptions, each in the format:\n",
    "                {class_name}<loc_{x1}><loc_{y1}><loc_{x2}><loc_{y2}>.\n",
    "                The class_name is replaced with a descriptive label, and x1, y1, x2, y2 are the coordinates of the bounding box vertices.\n",
    "    \"\"\"\n",
    "    # opening the file\n",
    "    with open(annotation_file, 'r') as f:\n",
    "        lines = f.readlines()\n",
    "\n",
    "    image_name = os.path.basename(annotation_file).replace('.txt', '.jpg')\n",
    "    prefix = \"<OD>\"\n",
    "    suffix_lines = []\n",
    "\n",
    "    # Processing\n",
    "    for line in lines:\n",
    "        parts = line.strip().split()\n",
    "        class_name = parts[0]\n",
    "        x_center = float(parts[1])\n",
    "        y_center = float(parts[2])\n",
    "        width = float(parts[3])\n",
    "        height = float(parts[4])\n",
    "\n",
    "        x1 = int((x_center - width / 2) * 1000)\n",
    "        y1 = int((y_center - height / 2) * 1000)\n",
    "        x2 = int((x_center + width / 2) * 1000)\n",
    "        y2 = int((y_center + height / 2) * 1000)\n",
    "\n",
    "        # Replacing class values with class labels\n",
    "        if class_name == '0':\n",
    "            class_name = 'DC Power Supply'\n",
    "        elif class_name == '1':\n",
    "            class_name = 'Digital Multimeter'\n",
    "        elif class_name == '2':\n",
    "            class_name = 'Digital Trainer'\n",
    "        elif class_name == '3':\n",
    "            class_name = 'Function Generator'\n",
    "        elif class_name == '4':\n",
    "            class_name = 'Oscilloscope'\n",
    "        suffix_line = f\"{class_name}<loc_{x1}><loc_{y1}><loc_{x2}><loc_{y2}>\"\n",
    "        suffix_lines.append(suffix_line)\n",
    "\n",
    "    # Return json object\n",
    "    json_obj = {\n",
    "        \"image\": image_name,\n",
    "        \"prefix\": prefix,\n",
    "        \"suffix\": \"\".join(suffix_lines)\n",
    "    }\n",
    "\n",
    "    return json_obj"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e0f4b498-35de-4386-8b4d-d95748360ac8",
   "metadata": {},
   "outputs": [],
   "source": [
    "TRAIN_DIR = \"images/train\"\n",
    "VALID_DIR = \"images/valid\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16a3b294-4651-4e9b-871b-375366500c82",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "42ce333b-f9b1-4412-be9f-a286895861b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_annotations_dir = os.path.join(TRAIN_DIR, \"labels\")\n",
    "train_json_file = os.path.join(TRAIN_DIR, \"images/train_annotations.json\")\n",
    "\n",
    "train_annotations_list = []\n",
    "\n",
    "for filename in os.listdir(train_annotations_dir):\n",
    "    if filename.endswith(\".txt\"):\n",
    "        annotation_file = os.path.join(train_annotations_dir, filename)\n",
    "        annotation_obj = yolo_parsing(annotation_file)\n",
    "        json_string = json.dumps(annotation_obj, separators=(',', ':'))\n",
    "        train_annotations_list.append(json_string)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "edc61116-15ac-44d5-855f-b25cad8dc665",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2379"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_annotations_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3f528e40-fb67-4843-bc02-f7365048a3a8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Annotations have been written to images/train/images/train_annotations.json\n"
     ]
    }
   ],
   "source": [
    "with open(train_json_file, 'w') as json_file:\n",
    "    json_file.write(\"\\n\".join(train_annotations_list))\n",
    "\n",
    "print(f\"Annotations have been written to {train_json_file}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c0c52cd8-8f45-4217-997d-f914817dc760",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rwxrwxrwx 1 root root 374K Jan 14 10:24 images/train/images/train_annotations.json\n"
     ]
    }
   ],
   "source": [
    "!ls $train_json_file -lh"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e125530-7530-4932-b83a-ff2fe5627611",
   "metadata": {},
   "source": [
    "## Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "5f063363-bc16-4603-8078-ad9946889528",
   "metadata": {},
   "outputs": [],
   "source": [
    "valid_annotations_dir = os.path.join(VALID_DIR, \"labels\")\n",
    "valid_json_file = os.path.join(VALID_DIR, \"images/val_annotations.json\")\n",
    "\n",
    "valid_annotations_list = []\n",
    "\n",
    "for filename in os.listdir(valid_annotations_dir):\n",
    "    if filename.endswith(\".txt\"):\n",
    "        annotation_file = os.path.join(valid_annotations_dir, filename)\n",
    "        annotation_obj = yolo_parsing(annotation_file)\n",
    "        json_string = json.dumps(annotation_obj, separators=(',', ':'))\n",
    "        valid_annotations_list.append(json_string)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "977bf23d-525f-45e2-99e4-2fb94ede7600",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "123"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(valid_annotations_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f7428b67-c33f-4a5f-a2b6-e2babd53ab63",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Annotations have been written to images/valid/images/val_annotations.json\n"
     ]
    }
   ],
   "source": [
    "with open(valid_json_file, 'w') as json_file:\n",
    "    json_file.write(\"\\n\".join(valid_annotations_list))\n",
    "\n",
    "print(f\"Annotations have been written to {valid_json_file}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3a7ac5db-7b9c-4192-bc9f-9fb126c67d12",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rwxrwxrwx 1 root root 20K Jan 14 10:24 images/valid/images/val_annotations.json\n"
     ]
    }
   ],
   "source": [
    "!ls $valid_json_file -lh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38e5e6e2-803c-434a-bc42-0e2a3ba61f42",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10 - SDK v2",
   "language": "python",
   "name": "python310-sdkv2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
